//
//  CNLSDataUpdate.swift
//  testDemo
//
//  Created by frank on 2021/4/6.
//  Copyright © 2021 Alexey Naumov. All rights reserved.
//

import Foundation
import UIKit

class DataUpdate: NSObject {
    
    func getDataWithParam(_ params:Dictionary<String, Any> , _ url:String, _ handler:@escaping(_ isSuccuess:Bool ,_ response:Dictionary<String,Any>,_ errorMsg:String) -> Void) throws -> Void{
        let client = AFAPPClient.sharedInstance
        let myUrl = ApiBaseUrl + url
        client.get(myUrl, parameters: params) { (progress:Progress) in
            
        } success: { (task:URLSessionDataTask , response:Any) in
            SLog.verbose("请求成功\n 头: '\(client.requestSerializer.httpRequestHeaders)' \n 请求方式:GET \n 请求URL:'\(url)' params:'\(params)'\n response:\(response)")
            let code : Int = (response as! Dictionary<String,Any>)["code"] as! Int
            if self.dealWithCodeCanNext(code){
                handler(true,response as! Dictionary<String, Any>,"")
            }else{
                handler(false,response as! Dictionary<String, Any>,"")
            }
            
            
        } failure: { (task:URLSessionDataTask? , error:Error) in
            let code = (error as NSError).code
            var message = error.message(code: code)
            if message.count > 0{
                message = "错误信息：\(message)"
            }
            SLog.error("请求失败,\(message) \n error: \(error.localizedDescription)")
            handler(false,Dictionary(),"")
        }

    }
    
    
    func postDataWithParam(_ params:Dictionary<String, Any> , _ url:String, _ handler:@escaping(_ isSuccuess:Bool ,_ response:Dictionary<String,Any>,_ errorMsg:String) -> Void) throws -> Void {
        let client = AFAPPClient.sharedInstance
        let myUrl = ApiBaseUrl + url
        client.post(myUrl, parameters: params) { (progress:Progress) in
            
        } success: { (task:URLSessionDataTask , response:Any) in
            SLog.verbose("请求成功\n 头: '\(client.requestSerializer.httpRequestHeaders)' \n 请求方式:GET \n 请求URL:'\(url)' params:'\(params)'\n response:\(response)")

            let code : Int = (response as! Dictionary<String,Any>)["code"] as! Int
            if self.dealWithCodeCanNext(code){
                handler(true,response as! Dictionary<String, Any>,"")
            }else{
                handler(false,response as! Dictionary<String, Any>,"")
            }
            
            // 存储cookie
            let myResponse = task.response as? HTTPURLResponse
            let fields = myResponse?.allHeaderFields
            var cookies: [HTTPCookie]? = nil
            if let fields = fields as? [String : String], let url = URL(string: myUrl) {
                cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
            }
            if (cookies?.count ?? 0 > 0 && myResponse?.statusCode != -100){
                self.setupCookie(url, cookies!)
            }
            
        } failure: { (task:URLSessionDataTask? , error:Error) in
            let code = (error as NSError).code
            var message = error.message(code: code)
            if message.count > 0{
                message = "错误信息：\(message)"
            }
            SLog.error("请求失败,\(message) \n error: \(error.localizedDescription)")
            handler(false,Dictionary(),"")
        }

    }
    
    //业务状态码处理
    private func dealWithCodeCanNext(_ code:Int) ->Bool{
        //    200     //正常请求
        //    10003   //token无效
        //    10004   //token过期
        //    -1      //其他错误
        switch code {
        case 200:
            return true
        case 10003:
            self.pushToLoginVc()
            return false
        case 10004:
            self.pushToLoginVc()
            return false
            
        default:
            return false
        }
    }
    
    func pushToLoginVc() -> Void{
        
    }
    
    //保存Cookie
    fileprivate func setupCookie(_ url:String, _ array:[Any]) ->Void{
        for cookie in array{
            if let myCookie = cookie as? HTTPCookie{
                var cookiesArray: [HTTPCookie]? = []
                var propertie = myCookie.properties

                propertie?[.expires] = Date(timeIntervalSinceNow: 365 * 24 * 60 * 60)
                propertie?[.path] = ""
                propertie?.removeValue(forKey: .discard)
                if let propertie = propertie, let cookie1 = HTTPCookie(properties: propertie) {
                        cookiesArray?.append(cookie1)
                    }
                HTTPCookieStorage.shared.setCookies(cookiesArray!, for: NSURL(string: url) as URL?, mainDocumentURL: nil)
                let requestFields = HTTPCookie.requestHeaderFields(with: cookiesArray!)
                UserDefaults.standard.setValue(requestFields["Cookie"] as Any,  "sessionCookie")
                AFAPPClient.sharedInstance.requestSerializer.setValue(requestFields["Cookie"], forKey: "Cookie")

            }
        }
    }
    
    //本地https证书路径
    fileprivate func customSecurityPolicy() -> AFSecurityPolicy{
        let cerPath = Bundle.main.path(forResource: "", ofType: "cer")
        let cerData = NSData(contentsOfFile: cerPath!) as Data?
        let set = Set<Data>([cerData!])
        let policy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.certificate, withPinnedCertificates: set)
        policy.validatesDomainName = false
        policy.allowInvalidCertificates = true
        return policy
    }
    
    class var sharedInstance: DataUpdate {
        var instance = DataUpdate()
        DispatchQueue.once {
            instance = DataUpdate.init()
        }
        return instance
    }
    
    private override init() {
        
    }
}


class AFAPPClient: AFHTTPSessionManager {
    class var sharedInstance: AFAPPClient {
        let instance = AFAPPClient()
        DispatchQueue.once {
            instance.securityPolicy = AFSecurityPolicy.init(pinningMode: AFSSLPinningMode.none)
            instance.responseSerializer = AFJSONResponseSerializer.init()
            instance.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json","text/json","text/javascript","text/html","text/plain","text/xml") as? Set<String>
            instance.requestSerializer.willChangeValue(forKey: "timeoutInterval")
            instance.requestSerializer.timeoutInterval = 15
            instance.requestSerializer.didChangeValue(forKey: "timeoutInterval")
            
//            instance.securityPolicy = DataUpdate.sharedInstance.customSecurityPolicy()
            
            let def = UserDefaults.standard
//            if def.object(forKey: "sessionCookie") != nil{
                instance.requestSerializer.setValue(def.object(forKey: "sessionCookie"), forKey: "sessionCookie")
//            }
        }
        return instance
    }
    
    
}

extension DispatchQueue {
    private static var _onceToken = [String]()
    
    class func once(token: String = "\(#file):\(#function):\(#line)", block: ()->Void) {
        objc_sync_enter(self)
        
        defer
        {
            objc_sync_exit(self)
        }

        if _onceToken.contains(token)
        {
            return
        }

        _onceToken.append(token)
        block()
    }
}
